// 功能
$(document).ready(function () {
  var chatBtn = $("#chatBtn");
  var chatInput = $("#chatInput");
  var chatWindow = $("#chatWindow");

  // 存储对话信息,实现连续对话
  var messages = [];

  // 检查返回的信息是否是正确信息
  var resFlag = true;

  // 创建自定义渲染器
  const renderer = new marked.Renderer();

  // 重写list方法
  renderer.list = function (body, ordered, start) {
    const type = ordered ? "ol" : "ul";
    const startAttr = ordered && start ? ` start="${start}"` : "";
    return `<${type}${startAttr}>\n${body}</${type}>\n`;
  };

  // 设置marked选项
  marked.setOptions({
    renderer: renderer,
    highlight: function (code, language) {
      const validLanguage = hljs.getLanguage(language)
        ? language
        : "javascript";
      return hljs.highlight(code, { language: validLanguage }).value;
    },
  });

  // 转义html代码(对应字符转移为html实体)，防止在浏览器渲染
  function escapeHtml(html) {
    let text = document.createTextNode(html);
    let div = document.createElement("div");
    div.appendChild(text);
    return div.innerHTML;
  }

  // 添加请求消息到窗口
  function addRequestMessage(message) {
    $(".answer .tips").css({ display: "none" }); // 打赏卡隐藏
    chatInput.val("");
    let escapedMessage = escapeHtml(message); // 对请求message进行转义，防止输入的是html而被浏览器渲染
    let requestMessageElement = $(
      '<div class="message-bubble"><span class="chat-icon request-icon"></span><div class="message-text request"><p>' +
        escapedMessage +
        "</p></div></div>"
    );
    chatWindow.append(requestMessageElement);
    let responseMessageElement = $(
      '<div class="message-bubble"><span class="chat-icon response-icon"></span><div class="message-text response"><span class="loading-icon"><i class="fa fa-spinner fa-pulse fa-2x"></i></span></div></div>'
    );
    chatWindow.append(responseMessageElement);
    chatWindow.scrollTop(chatWindow.prop("scrollHeight"));
  }

  // 添加响应消息到窗口,流式响应此方法会执行多次
  function addResponseMessage(message) {
    let lastResponseElement = $(".message-bubble .response").last();
    lastResponseElement.empty();
    let escapedMessage;
    // 处理流式消息中的代码块
    let codeMarkCount = 0;
    let index = message.indexOf("```");
    while (index !== -1) {
      codeMarkCount++;
      index = message.indexOf("```", index + 3);
    }
    if (codeMarkCount % 2 == 1) {
      // 有未闭合的 code
      escapedMessage = marked.parse(message + "\n\n```");
    } else if (codeMarkCount % 2 == 0 && codeMarkCount != 0) {
      escapedMessage = marked.parse(message); // 响应消息markdown实时转换为html
    } else if (codeMarkCount == 0) {
      // 输出的代码没有markdown代码块
      if (message.includes("`")) {
        escapedMessage = marked.parse(message); // 没有markdown代码块，但有代码段，依旧是markdown格式
      } else {
        escapedMessage = marked.parse(escapeHtml(message)); // 有可能不是markdown格式，都用escapeHtml处理后再转换，防止非markdown格式html紊乱页面
      }
    }
    lastResponseElement.append(escapedMessage);
    chatWindow.scrollTop(chatWindow.prop("scrollHeight"));
  }

  // 添加失败信息到窗口
  function addFailMessage(message) {
    let lastResponseElement = $(".message-bubble .response").last();
    lastResponseElement.empty();
    lastResponseElement.append('<p class="error">' + message + "</p>");
    chatWindow.scrollTop(chatWindow.prop("scrollHeight"));
    messages.pop(); // 失败就让用户输入信息从数组删除
  }

  async function pollTask(taskId, apiKey, maxAttempts = 20, interval = 5000) {
    for (let attempt = 0; attempt < maxAttempts; attempt++) {
      let requestUrl =
        "https://open.bigmodel.cn/api/paas/v4/async-result/" + taskId;
      let res = await fetch(requestUrl, {
        method: "GET",
        headers: { Authorization: "Bearer " + apiKey },
      }).then((data) => {
        return data.text();
      });
      res = JSON.parse(res);
      if (res.task_status === "SUCCESS") {
        console.log(res);
        let lastResponseElement = $(".message-bubble .response").last();
        let videoUrl = res.video_result[0].url;
        let coverImageUrl = res.video_result[0].cover_image_url;
        lastResponseElement.empty();
        lastResponseElement.append(
          `<video poster="${coverImageUrl}" controls src="${videoUrl}"></video>`
        );
        return;
      }

      await new Promise((resolve) => setTimeout(resolve, interval));
    }
    throw new Error("超时未获取结果");
  }

  // 发送请求获得响应
  async function sendRequest(data) {
    let params = {
      messages: data.prompts,
      model: $("#model-select").val() ? $("#model-select").val() : "glm-4.5-flash",
      max_tokens: 1025,
      temperature: 0.5,
      top_p: 1,
      n: 1,
      stream: true,
    };
    if ($("#model-select").val() == "cogview-3-flash") {
      params = {
        model: $("#model-select").val(),
        prompt: data.prompts[data.prompts.length - 1].content,
      };

      let lastResponseElement = $(".message-bubble .response").last();
      fetch(config.url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer " + data.apiKey,
        },
        body: JSON.stringify(params),
      })
        .then((data) => {
          return data.text(); // data.text()返回的是一个promise对象
        })
        .then((result) => {
          // 调用then这里获取的才是真正的数据
          result = JSON.parse(result);
          if (result.error) {
            lastResponseElement.empty();
            lastResponseElement.append(
              `<p style="color: red;">${result.error.message}</p>`
            );
            return;
          }
          let url = result.data[0].url;
          lastResponseElement.empty();
          lastResponseElement.append('<img src="' + url + '"></img>');
        });
      return;
    }

    if ($("#model-select").val() == "cogvideox-flash") {
      params = {
        model: $("#model-select").val(),
        prompt: data.prompts[data.prompts.length - 1].content,
        quality: "quality",
        with_audio: true,
        size: "1920x1080",
        fps: 30,
      };

      fetch(config.url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer " + data.apiKey,
        },
        body: JSON.stringify(params),
      })
        .then((data) => {
          return data.text(); // data.text()返回的是一个promise对象
        })
        .then(async (result) => {
          let id = JSON.parse(result).id;
          await pollTask(id, data.apiKey);
        });
      return;
    }

    if ($("#model-select").val() == "glm-4.5-flash") {
      const response = await fetch(config.url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer " + data.apiKey,
        },
        body: JSON.stringify(params),
      });

      const reader = response.body.getReader();
      let res = "";
      let str;
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          break;
        }
        str = "";
        res += new TextDecoder()
          .decode(value)
          .replace(/^data: /gm, "")
          .replace("[DONE]", "");
        const lines = res.trim().split(/[\n]+(?=\{)/);
        for (let i = 0; i < lines.length; i++) {
          const line = lines[i];
          let jsonObj;
          try {
            jsonObj = JSON.parse(line);
          } catch (e) {
            break;
          }
          if (jsonObj.choices && jsonObj.choices[0].delta.content) {
            str += jsonObj.choices[0].delta.content;
            addResponseMessage(str);
            resFlag = true;
          } else {
            if (jsonObj.error) {
              addFailMessage(
                jsonObj.error.type +
                  " : " +
                  jsonObj.error.message +
                  jsonObj.error.code
              );
              resFlag = false;
            }
          }
        }
      }
      return str;
    }
  }

  // 处理用户输入
  chatBtn.click(function () {
    // 解绑键盘事件
    chatInput.off("keydown", handleEnter);

    // 保存api key与对话数据
    let data;
    if (config.apiKey !== "") {
      data = { apiKey: atob(config.apiKey) };
    } else {
      data = { apiKey: "" };
    }

    let apiKey = localStorage.getItem("apiKey");
    if (apiKey) {
      data.apiKey = apiKey;
    }

    let message = chatInput.val();
    if (message.length == 0) {
      // 重新绑定键盘事件
      chatInput.on("keydown", handleEnter);
      return;
    }

    addRequestMessage(message);
    // 将用户消息保存到数组
    messages.push({ role: "user", content: message });
    // 收到回复前让按钮不可点击
    chatBtn.attr("disabled", true);

    if (messages.length > 40) {
      addFailMessage("此次对话长度过长，请点击下方删除按钮清除对话内容！");
      // 重新绑定键盘事件
      chatInput.on("keydown", handleEnter);
      chatBtn.attr("disabled", false); // 让按钮可点击
      return;
    }

    // 判读是否已开启连续对话
    if (localStorage.getItem("continuousDialogue") == "true") {
      // 控制上下文，对话长度超过4轮，取最新的3轮,即数组最后7条数据
      data.prompts = messages.slice(); // 拷贝一份全局messages赋值给data.prompts,然后对data.prompts处理
      if (data.prompts.length > 8) {
        data.prompts.splice(0, data.prompts.length - 7);
      }
    } else {
      data.prompts = messages.slice();
      data.prompts.splice(0, data.prompts.length - 1); // 未开启连续对话，取最后一条
    }

    sendRequest(data).then((res) => {
      chatInput.val("");
      // 收到回复，让按钮可点击
      chatBtn.attr("disabled", false);
      // 重新绑定键盘事件
      chatInput.on("keydown", handleEnter);
      // 判断是否是回复正确信息
      if (resFlag) {
        messages.push({ role: "assistant", content: res });
        // 判断是否本地存储历史会话
        if (localStorage.getItem("archiveSession") == "true") {
          localStorage.setItem("session", JSON.stringify(messages));
        }
      }
      // 添加复制
      copy();
    });
  });

  // Enter键盘事件
  function handleEnter(e) {
    if (e.keyCode == 13) {
      chatBtn.click();
      e.preventDefault(); //避免回车换行
    }
  }

  // 绑定Enter键盘事件
  chatInput.on("keydown", handleEnter);

  // 设置栏宽度自适应
  let width = $(".function .others").width();
  $(".function .settings .dropdown-menu").css("width", width);

  $(window).resize(function () {
    width = $(".function .others").width();
    $(".function .settings .dropdown-menu").css("width", width);
  });

  // 主题
  function setBgColor(theme) {
    $(":root").attr("bg-theme", theme);
    $(".settings-common .theme").val(theme);
    // 定位在文档外的元素也同步主题色
    $(".settings-common").css("background-color", "var(--bg-color)");
  }

  let theme = localStorage.getItem("theme");
  // 如果之前选择了主题，则将其应用到网站中
  if (theme) {
    setBgColor(theme);
  } else {
    localStorage.setItem("theme", "light"); //默认的主题
    theme = localStorage.getItem("theme");
    setBgColor(theme);
  }

  // 监听主题选择的变化
  $(".settings-common .theme").change(function () {
    const selectedTheme = $(this).val();
    localStorage.setItem("theme", selectedTheme);
    $(":root").attr("bg-theme", selectedTheme);
    // 定位在文档外的元素也同步主题色
    $(".settings-common").css("background-color", "var(--bg-color)");
  });

  // apiKey
  const apiKey = localStorage.getItem("apiKey");
  if (apiKey) {
    $(".settings-common .api-key").val(apiKey);
  }

  // apiKey输入框事件
  $(".settings-common .api-key").blur(function () {
    const apiKey = $(this).val();
    if (apiKey.length != 0) {
      localStorage.setItem("apiKey", apiKey);
    } else {
      localStorage.removeItem("apiKey");
    }
  });

  // 是否保存历史对话
  var archiveSession = localStorage.getItem("archiveSession");

  // 初始化archiveSession
  if (archiveSession == null) {
    archiveSession = "false";
    localStorage.setItem("archiveSession", archiveSession);
  }

  if (archiveSession == "true") {
    $("#chck-1").prop("checked", true);
  } else {
    $("#chck-1").prop("checked", false);
  }

  $("#chck-1").click(function () {
    if ($(this).prop("checked")) {
      // 开启状态的操作
      localStorage.setItem("archiveSession", true);
      if (messages.length != 0) {
        localStorage.setItem("session", JSON.stringify(messages));
      }
    } else {
      // 关闭状态的操作
      localStorage.setItem("archiveSession", false);
      localStorage.removeItem("session");
    }
  });

  // 加载历史保存会话
  if (archiveSession == "true") {
    const messagesList = JSON.parse(localStorage.getItem("session"));
    if (messagesList) {
      messages = messagesList;
      $.each(messages, function (index, item) {
        if (item.role === "user") {
          addRequestMessage(item.content);
        } else if (item.role === "assistant") {
          addResponseMessage(item.content);
        }
      });
      // 添加复制
      copy();
    }
  }

  // 是否连续对话
  var continuousDialogue = localStorage.getItem("continuousDialogue");

  // 初始化continuousDialogue
  if (continuousDialogue == null) {
    continuousDialogue = "true";
    localStorage.setItem("continuousDialogue", continuousDialogue);
  }

  if (continuousDialogue == "true") {
    $("#chck-2").prop("checked", true);
  } else {
    $("#chck-2").prop("checked", false);
  }

  $("#chck-2").click(function () {
    if ($(this).prop("checked")) {
      localStorage.setItem("continuousDialogue", true);
    } else {
      localStorage.setItem("continuousDialogue", false);
    }
  });

  // 删除功能
  $(".delete a").click(function () {
    chatWindow.empty();
    $(".answer .tips").css({ display: "flex" });
    messages = [];
    localStorage.removeItem("session");
  });

  // 截图功能
  $(".screenshot a").click(function () {
    // 创建副本元素
    const clonedChatWindow = chatWindow.clone();
    clonedChatWindow.css({
      position: "absolute",
      left: "-9999px",
      overflow: "visible",
      width: chatWindow.width(),
      height: "auto",
    });
    $("body").append(clonedChatWindow);
    // 截图
    html2canvas(clonedChatWindow[0], {
      allowTaint: false,
      useCORS: true,
      scrollY: 0,
    }).then(function (canvas) {
      // 将 canvas 转换成图片
      const imgData = canvas.toDataURL("image/png");
      // 创建下载链接
      const link = document.createElement("a");
      link.download = "screenshot_" + Math.floor(Date.now() / 1000) + ".png";
      link.href = imgData;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      clonedChatWindow.remove();
    });
  });

  // 复制代码功能
  function copy() {
    $("pre").each(function () {
      let btn = $('<button class="copy-btn">复制</button>');
      $(this).append(btn);
      btn.hide();
    });

    $("pre").hover(
      function () {
        $(this).find(".copy-btn").show();
      },
      function () {
        $(this).find(".copy-btn").hide();
      }
    );

    $("pre").on("click", ".copy-btn", function () {
      let text = $(this).siblings("code").text();
      // 创建一个临时的 textarea 元素
      let textArea = document.createElement("textarea");
      textArea.value = text;
      document.body.appendChild(textArea);

      // 选择 textarea 中的文本
      textArea.select();

      // 执行复制命令
      try {
        document.execCommand("copy");
        $(this).text("复制成功");
      } catch (e) {
        $(this).text("复制失败");
      }

      // 从文档中删除临时的 textarea 元素
      document.body.removeChild(textArea);

      setTimeout(() => {
        $(this).text("复制");
      }, 2000);
    });
  }

  // 禁用右键菜单
  document.addEventListener("contextmenu", function (e) {
    e.preventDefault(); // 阻止默认事件
  });

  // 禁止键盘F12键
  document.addEventListener("keydown", function (e) {
    if (e.key == "F12") {
      e.preventDefault(); // 如果按下键F12,阻止事件
    }
  });
});
